from typing import Dict
import logging
import pandas as pd
from openai import OpenAI
import time

# 创建日志记录器
logger = logging.getLogger(__name__)

# 尝试修复httpx代理问题
try:
    import httpx
    
    # 检查是否需要进行monkey patch
    original_client = httpx.Client
    test_client_args = {'proxies': None}
    try:
        # 尝试创建带有proxies参数的客户端
        test_client = original_client(**test_client_args)
        logger.info("httpx.Client支持proxies参数，无需修复")
    except TypeError:
        logger.warning("检测到httpx.Client不支持proxies参数，应用monkey patch")
        
        # 定义不接受proxies参数的Client类
        class ClientWithoutProxies(original_client):
            def __init__(self, **kwargs):
                if 'proxies' in kwargs:
                    logger.info("拦截并移除了proxies参数")
                    del kwargs['proxies']
                super().__init__(**kwargs)
        
        # 替换httpx.Client
        httpx.Client = ClientWithoutProxies
        
        # 同样处理AsyncClient
        original_async_client = httpx.AsyncClient
        
        class AsyncClientWithoutProxies(original_async_client):
            def __init__(self, **kwargs):
                if 'proxies' in kwargs:
                    logger.info("拦截并移除了异步客户端的proxies参数")
                    del kwargs['proxies']
                super().__init__(**kwargs)
        
        # 替换httpx.AsyncClient
        httpx.AsyncClient = AsyncClientWithoutProxies
        
        logger.info("成功应用httpx客户端monkey patch")
except Exception as e:
    logger.warning(f"应用httpx代理问题修复失败: {str(e)}")

def get_result_preview_data(task_id):
    """获取结果预览数据
    
    Args:
        task_id: 任务ID
        
    Returns:
        DataFrame: 结果数据
    """
    logger.warning("get_result_preview_data函数尚未实现")
    # 这里应该实现获取预览数据的逻辑
    # 暂时返回None表示未实现
    return None


def get_result_stats(task_id):
    """获取结果统计信息"""
    # 获取结果预览
    result_df = get_result_preview_data(task_id)
    if result_df is None or result_df.empty:
        return {"error": "无预览数据"}

    # 获取总产品数
    total_products = len(result_df)
    
    # 获取品牌统计
    brand_counts = result_df['brand'].value_counts().to_dict()
    
    # 单位统计
    unit_counts = result_df['unit'].value_counts().to_dict()
    standard_unit_counts = result_df['standard_unit'].value_counts().to_dict()
    
    # 提取方式统计
    extract_method_counts = None
    if 'extract_method' in result_df.columns:
        extract_method_counts = result_df['extract_method'].value_counts().to_dict()
    
    # 置信度区间统计
    confidence_intervals = {
        "很高(>80)": ((result_df['confidence_score'] > 80) & (result_df['confidence_score'] <= 100)).sum(),
        "高(60-80)": ((result_df['confidence_score'] > 60) & (result_df['confidence_score'] <= 80)).sum(),
        "中(40-60)": ((result_df['confidence_score'] > 40) & (result_df['confidence_score'] <= 60)).sum(),
        "低(20-40)": ((result_df['confidence_score'] > 20) & (result_df['confidence_score'] <= 40)).sum(),
        "很低(<20)": ((result_df['confidence_score'] >= 0) & (result_df['confidence_score'] <= 20)).sum(),
    }
    
    # 价格统计（按标准单位分组）
    price_stats = {}
    for unit in result_df['standard_unit'].unique():
        unit_df = result_df[result_df['standard_unit'] == unit]
        if 'standard_price' in unit_df.columns and not unit_df['standard_price'].isna().all():
            price_stats[unit] = {
                "min": unit_df['standard_price'].min(),
                "max": unit_df['standard_price'].max(),
                "mean": unit_df['standard_price'].mean(),
                "median": unit_df['standard_price'].median(),
            }
    
    # 获取置信度统计
    confidence_stats = None
    if 'confidence_score' in result_df.columns:
        confidence_stats = {
            "min": result_df['confidence_score'].min(),
            "max": result_df['confidence_score'].max(),
            "mean": result_df['confidence_score'].mean(),
            "median": result_df['confidence_score'].median(),
        }
        
        # 按品牌的置信度统计
        brand_confidence = {}
        for brand in result_df['brand'].unique():
            if pd.notna(brand) and brand:
                brand_df = result_df[result_df['brand'] == brand]
                brand_confidence[brand] = {
                    "mean": brand_df['confidence_score'].mean(),
                    "count": len(brand_df)
                }
        
        confidence_stats["brand_confidence"] = brand_confidence
    
    stats = {
        "total_products": total_products,
        "brand_distribution": brand_counts,
        "unit_distribution": unit_counts,
        "standard_unit_distribution": standard_unit_counts,
        "confidence_intervals": confidence_intervals,
        "price_stats": price_stats
    }
    
    if confidence_stats:
        stats["confidence_stats"] = confidence_stats
        
    if extract_method_counts:
        stats["extract_method_distribution"] = extract_method_counts
    
    return stats 

def call_deepseek_api(prompt: str, config_manager=None) -> Dict:
    """使用OpenAI SDK调用DeepSeek API
    
    Args:
        prompt: 提示词
        config_manager: 配置管理器
        
    Returns:
        API响应
    """
    import os
    
    # 1. 获取API密钥
    api_key = None
    
    # 从配置管理器获取
    if config_manager:
        try:
            if hasattr(config_manager, '_is_initialized') and config_manager._is_initialized:
                if hasattr(config_manager, '_system_config'):
                    api_key = config_manager._system_config.get("DEEPSEEK_API_KEY")
                    if api_key:
                        # logger.info("从配置管理器获取DeepSeek API密钥成功")
                        pass
                    else:
                        logger.warning("配置管理器中未找到DEEPSEEK_API_KEY")
                else:
                    logger.warning("配置管理器未包含系统配置信息")
            else:
                logger.warning("配置管理器未初始化，将尝试从环境变量获取密钥")
        except Exception as e:
            logger.warning(f"从配置管理器获取密钥失败: {str(e)}")
    
    # 从环境变量获取
    if not api_key:
        try:
            api_key = os.environ.get("DEEPSEEK_API_KEY")
            if api_key:
                # logger.info("使用环境变量中的DeepSeek密钥")
                pass
        except Exception as e:
            logger.warning(f"从环境变量获取密钥失败: {str(e)}")
    
    # 从.env文件获取（仅用于开发测试）
    if not api_key:
        try:
            env_path = os.path.join(os.getcwd(), '.env')
            if os.path.exists(env_path):
                with open(env_path, 'r') as f:
                    for line in f:
                        if line.startswith('DEEPSEEK_API_KEY='):
                            api_key = line.strip().split('=', 1)[1].strip('"\'')
                            if api_key:
                                logger.info("使用.env文件中的DeepSeek密钥")
                                break
        except Exception as e:
            logger.warning(f"从.env文件获取密钥失败: {str(e)}")
    
    # 最终检查
    if not api_key:
        error_msg = "未能获取DEEPSEEK_API_KEY，请在配置管理器、环境变量或.env文件中设置"
        logger.error(error_msg)
        raise ValueError(error_msg)
    
    # 2. 获取其他API设置
    base_url = "https://api.deepseek.com"  # 默认URL
    model = "deepseek-chat"  # 默认模型
    temperature = 0.1  # 默认温度
    max_tokens = 1024  # 默认最大token数 - 使用相对合适的默认值
    
    # 从配置管理器获取更多设置
    if config_manager and hasattr(config_manager, '_is_initialized') and config_manager._is_initialized and hasattr(config_manager, '_system_config'):
        system_config = config_manager._system_config
        
        # API URL
        if "DEEPSEEK_API_URL" in system_config:
            base_url = system_config.get("DEEPSEEK_API_URL", base_url)
            logger.info(f"从配置获取API URL: {base_url}")
        else:
            logger.warning("配置中缺少DEEPSEEK_API_URL，使用默认值")
        
        # 模型名称
        if "DEEPSEEK_MODEL" in system_config:
            model = system_config.get("DEEPSEEK_MODEL", model)
            # logger.info(f"从配置获取模型名称: {model}")
        else:
            logger.warning("配置中缺少DEEPSEEK_MODEL，使用默认值deepseek-chat")
            
        # 温度
        if "DEEPSEEK_TEMPERATURE" in system_config:
            try:
                temperature = float(system_config.get("DEEPSEEK_TEMPERATURE"))
                temperature = max(0.0, min(1.0, temperature))
                # logger.info(f"从配置获取温度值: {temperature}")
            except Exception as e:
                logger.warning(f"温度值解析错误: {str(e)}")
                
        # 最大token数
        if "DEEPSEEK_MAX_TOKENS" in system_config:
            try:
                max_tokens_parsed = int(system_config.get("DEEPSEEK_MAX_TOKENS"))
                # 确保max_tokens在DeepSeek API允许范围内 (1-8192)
                max_tokens = max(1, min(8192, max_tokens_parsed))
                # logger.info(f"从配置获取最大token数: {max_tokens}")
            except Exception as e:
                logger.warning(f"最大token数解析错误: {str(e)}")
    else:
        logger.warning("配置管理器未初始化或不包含系统配置，使用默认API设置")
    
    # 从环境变量获取更多设置
    env_api_url = os.environ.get("DEEPSEEK_API_URL")
    if env_api_url:
        base_url = env_api_url
        # logger.info(f"从环境变量获取API URL: {base_url}")
    
    env_model = os.environ.get("DEEPSEEK_MODEL")
    if env_model:
        model = env_model
        # logger.info(f"从环境变量获取模型名称: {model}")
    
    try:
        temp_env = os.environ.get("DEEPSEEK_TEMPERATURE")
        if temp_env:
            temperature = float(temp_env)
            temperature = max(0.0, min(1.0, temperature))
            # logger.info(f"从环境变量获取温度值: {temperature}")
    except Exception as e:
        logger.warning(f"解析环境变量温度值失败: {str(e)}")
        
    try:
        tokens_env = os.environ.get("DEEPSEEK_MAX_TOKENS")
        if tokens_env:
            max_tokens_parsed = int(tokens_env)
            # 确保max_tokens在DeepSeek API允许范围内 (1-8192)
            max_tokens = max(1, min(8192, max_tokens_parsed))
            # logger.info(f"从环境变量获取max_tokens值: {max_tokens}")
    except Exception as e:
        logger.warning(f"解析环境变量max_tokens值失败: {str(e)}")
    
    # 最终配置汇总
    # logger.info(f"最终DeepSeek API配置 - 基础URL: {base_url}, 模型: {model}, 温度: {temperature}, 最大token数: {max_tokens}")
    # logger.info(f"请求提示词长度: {len(prompt)} 字符")
    # logger.info(f"请求提示词前8000字符: {prompt[:8000]}...")
    
    # 3. 使用OpenAI SDK调用API
    max_retries = 3
    current_retry = 0
    retry_delay = 5
    
    while current_retry < max_retries:
        try:
            logger.info(f"==== 调用DeepSeek API开始 (尝试 {current_retry+1}/{max_retries}) ====")
            
            # 检查环境变量中是否存在代理配置
            # 注意：OpenAI客户端不直接支持proxies参数，需要通过环境变量设置
            http_proxy = os.environ.get("HTTP_PROXY")
            https_proxy = os.environ.get("HTTPS_PROXY")
            if http_proxy or https_proxy:
                logger.info(f"检测到代理设置: HTTP_PROXY={http_proxy}, HTTPS_PROXY={https_proxy}")
                logger.warning("OpenAI SDK不支持直接传入proxies参数，将通过环境变量设置")
            
            # 初始化OpenAI客户端 - 只传入必要的参数
            client = OpenAI(
                api_key=api_key,
                base_url=base_url
            )
            
            # 调用API
            response = client.chat.completions.create(
                model=model,
                messages=[
                    {"role": "system", "content": "你是一位专业的商品数据清洗和标准化专家，擅长从商品描述中提取结构化信息。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=temperature,
                max_tokens=max_tokens,
                stream=False
            )
            
            # 转换为字典格式，与旧API保持一致
            response_dict = {
                "id": response.id,
                "object": response.object,
                "created": response.created,
                "model": response.model,
                "choices": [
                    {
                        "index": choice.index,
                        "message": {
                            "role": choice.message.role,
                            "content": choice.message.content
                        },
                        "finish_reason": choice.finish_reason
                    } for choice in response.choices
                ]
            }
            
            # 记录令牌使用情况
            if hasattr(response, 'usage'):
                response_dict["usage"] = {
                    "prompt_tokens": response.usage.prompt_tokens,
                    "completion_tokens": response.usage.completion_tokens,
                    "total_tokens": response.usage.total_tokens
                }
                logger.info(f"DeepSeek API令牌使用情况: 提示词={response.usage.prompt_tokens}, "
                           f"完成={response.usage.completion_tokens}, "
                           f"总计={response.usage.total_tokens}")
            
            # 记录响应内容
            if response.choices and len(response.choices) > 0:
                content = response.choices[0].message.content
                logger.info(f"DeepSeek API响应内容长度: {len(content)} 字符")
                logger.info(f"DeepSeek API响应内容前500字符: {content[:500]}...")
            else:
                logger.warning("DeepSeek API响应中没有找到有效内容")
            
            logger.info(f"==== 调用DeepSeek API结束 ====")
            return response_dict
            
        except Exception as e:
            logger.error(f"调用DeepSeek API失败: {str(e)}")
            current_retry += 1
            
            if current_retry < max_retries:
                retry_wait = retry_delay * (2 ** (current_retry - 1))  # 指数退避策略
                logger.warning(f"等待 {retry_wait} 秒后重试...")
                time.sleep(retry_wait)
            else:
                logger.error(f"DeepSeek API在 {max_retries} 次尝试后仍然失败")
                raise Exception(f"DeepSeek API调用失败: {str(e)}") 